#!/usr/bin/env python3
"""
硬件检测模块
用于检测CPU、集显、独显等硬件信息
简化检测逻辑，使用psutil进行存在性检测
"""

import platform
import subprocess
import re
from typing import Dict, List, Optional


class HardwareDetector:
    """硬件检测器"""
    
    def __init__(self):
        self.system_info = {}
        self.cpu_info = {}
        self.gpu_info = {}
        self.detect_hardware()
    
    def detect_hardware(self):
        """检测硬件信息"""
        self._detect_system_info()
        self._detect_cpu_info()
        self._detect_gpu_info()
    
    def _detect_system_info(self):
        """检测系统信息"""
        self.system_info = {
            "platform": platform.system(),
            "platform_version": platform.version(),
            "architecture": platform.architecture()[0],
            "processor": platform.processor(),
            "machine": platform.machine()
        }
    
    def _detect_cpu_info(self):
        """检测CPU信息"""
        try:
            # 使用psutil检测CPU基本信息
            import psutil
            
            # 改进CPU名称检测
            cpu_name = self._get_detailed_cpu_name()
            cpu_cores = psutil.cpu_count(logical=False)
            cpu_threads = psutil.cpu_count(logical=True)
            
            # 检测CPU制造商
            manufacturer = self._get_cpu_manufacturer(cpu_name)
            
            # 检测是否有集成显卡
            has_igpu = self._check_cpu_has_igpu(cpu_name, manufacturer)
            
            self.cpu_info = {
                "name": cpu_name,
                "cores": cpu_cores,
                "threads": cpu_threads,
                "manufacturer": manufacturer,
                "has_integrated_graphics": has_igpu
            }
        except Exception as e:
            # 如果检测失败，提供默认值
            self.cpu_info = {
                "name": "未知CPU",
                "cores": 4,
                "threads": 8,
                "manufacturer": "未知",
                "has_integrated_graphics": False
            }
    
    def _detect_gpu_info(self):
        """检测GPU信息"""
        self.gpu_info = {
            "integrated_gpus": [],
            "dedicated_gpus": []
        }
        
        try:
            # 先检测CPU类型，然后检测对应的集显
            cpu_manufacturer = self.cpu_info.get("manufacturer", "")
            has_igpu = self.cpu_info.get("has_integrated_graphics", False)
            
            # 检测集成显卡
            if has_igpu:
                # 实际检测系统中是否存在集成显卡
                igpu_name = self._detect_integrated_gpu()
                if igpu_name:
                    self.gpu_info["integrated_gpus"].append({
                        "name": igpu_name,
                        "type": "integrated",
                        "vendor": cpu_manufacturer
                    })
            
            # 检测独立显卡
            dgpu_name = self._detect_dedicated_gpu()
            if dgpu_name:
                vendor = self._get_gpu_vendor(dgpu_name)
                self.gpu_info["dedicated_gpus"].append({
                    "name": dgpu_name,
                    "type": "dedicated",
                    "vendor": vendor
                })
                
        except Exception as e:
            # 如果检测失败，提供默认值
            self.gpu_info["integrated_gpus"] = []
            self.gpu_info["dedicated_gpus"] = []
    
    def _get_cpu_manufacturer(self, cpu_name: str) -> str:
        """获取CPU制造商"""
        cpu_name_lower = cpu_name.lower()
        
        if "intel" in cpu_name_lower:
            return "Intel"
        elif "amd" in cpu_name_lower:
            return "AMD"
        else:
            return "未知"
    
    def _check_cpu_has_igpu(self, cpu_name: str, manufacturer: str) -> bool:
        """检查CPU是否有集成显卡"""
        cpu_name_lower = cpu_name.lower()
        
        # Intel CPU通常有集成显卡（除了部分服务器CPU）
        if manufacturer == "Intel":
            # 检查是否为服务器CPU（Xeon系列通常没有集成显卡）
            if "xeon" in cpu_name_lower:
                return False
            return True
        
        # AMD CPU：Ryzen系列部分有集成显卡（APU系列）
        elif manufacturer == "AMD":
            # AMD Ryzen APU系列有集成显卡
            # 放宽检测条件：包含Ryzen且包含G/H/U后缀，或者直接检测硬件
            if "ryzen" in cpu_name_lower:
                # 检查常见APU后缀
                if any(suffix in cpu_name_lower for suffix in ['g', 'h', 'u', 'apu']):
                    return True
                # 如果CPU名称不明确，尝试实际硬件检测
                return self._try_hardware_detection()
            return False
        
        return False
    
    def _get_detailed_cpu_name(self) -> str:
        """获取详细的CPU名称"""
        try:
            # 首先尝试使用platform.processor()
            cpu_name = platform.processor()
            
            # 如果返回的是通用名称，尝试使用WMI获取更详细的信息
            if cpu_name in ['', 'AMD64 Family', 'Intel64 Family'] or 'Family' in cpu_name:
                if platform.system() == "Windows":
                    try:
                        import wmi
                        c = wmi.WMI()
                        for processor in c.Win32_Processor():
                            if processor.Name:
                                return processor.Name
                    except:
                        pass
            
            # 如果WMI也失败，尝试使用其他方法
            if cpu_name in ['', 'AMD64 Family', 'Intel64 Family']:
                # 使用系统命令获取CPU信息
                if platform.system() == "Windows":
                    try:
                        result = subprocess.run(['wmic', 'cpu', 'get', 'name'], capture_output=True, text=True)
                        if result.returncode == 0:
                            lines = result.stdout.strip().split('\n')
                            if len(lines) > 1 and lines[1].strip():
                                return lines[1].strip()
                    except:
                        pass
            
            return cpu_name if cpu_name else "未知CPU"
        except:
            return "未知CPU"
    
    def _try_hardware_detection(self) -> bool:
        """尝试通过硬件检测来判断是否有集显"""
        try:
            if platform.system() == "Windows":
                # 在Windows上尝试检测Intel或AMD集成显卡
                igpu_name = self._detect_integrated_gpu_windows()
                return bool(igpu_name)
            else:
                # 在Linux上尝试检测集成显卡
                igpu_name = self._detect_integrated_gpu_linux()
                return bool(igpu_name)
        except:
            return False
    
    def _get_detailed_cpu_name(self) -> str:
        """获取详细的CPU名称"""
        try:
            # 首先尝试使用platform.processor()
            cpu_name = platform.processor()
            
            # 如果返回的是通用名称，尝试使用WMI获取更详细的信息
            if cpu_name in ['', 'AMD64 Family', 'Intel64 Family'] or 'Family' in cpu_name:
                if platform.system() == "Windows":
                    try:
                        import wmi
                        c = wmi.WMI()
                        for processor in c.Win32_Processor():
                            if processor.Name:
                                return processor.Name
                    except:
                        pass
            
            # 如果WMI也失败，尝试使用其他方法
            if cpu_name in ['', 'AMD64 Family', 'Intel64 Family']:
                # 使用系统命令获取CPU信息
                if platform.system() == "Windows":
                    try:
                        result = subprocess.run(['wmic', 'cpu', 'get', 'name'], capture_output=True, text=True)
                        if result.returncode == 0:
                            lines = result.stdout.strip().split('\n')
                            if len(lines) > 1 and lines[1].strip():
                                return lines[1].strip()
                    except:
                        pass
            
            return cpu_name if cpu_name else "未知CPU"
        except:
            return "未知CPU"
    
    def _try_hardware_detection(self) -> bool:
        """尝试通过硬件检测来判断是否有集显"""
        try:
            if platform.system() == "Windows":
                # 在Windows上尝试检测Intel或AMD集成显卡
                igpu_name = self._detect_integrated_gpu_windows()
                return bool(igpu_name)
            else:
                # 在Linux上尝试检测集成显卡
                igpu_name = self._detect_integrated_gpu_linux()
                return bool(igpu_name)
        except:
            return False
    
    def _detect_integrated_gpu(self) -> str:
        """检测集成显卡"""
        try:
            if platform.system() == "Windows":
                return self._detect_integrated_gpu_windows()
            else:
                return self._detect_integrated_gpu_linux()
        except:
            return ""
    
    def _detect_integrated_gpu_windows(self) -> str:
        """Windows系统检测集成显卡"""
        try:
            import wmi
            c = wmi.WMI()
            
            # 收集所有显卡信息
            gpu_list = []
            for gpu in c.Win32_VideoController():
                gpu_name = gpu.Name
                if gpu_name and "Microsoft" not in gpu_name and "Remote" not in gpu_name:
                    gpu_list.append(gpu_name)
            
            # 优先检测集成显卡
            for gpu_name in gpu_list:
                gpu_name_lower = gpu_name.lower()
                
                # 检测Intel集成显卡
                if "intel" in gpu_name_lower or "integrated" in gpu_name_lower:
                    return "Intel 集成显卡"
                
                # 检测AMD集成显卡（放宽条件）
                elif "amd" in gpu_name_lower:
                    # AMD集成显卡通常包含Radeon Graphics或Vega Graphics
                    if "radeon" in gpu_name_lower or "vega" in gpu_name_lower:
                        return "AMD 集成显卡"
                    # 如果只有一个AMD显卡，且不是明显的独立显卡，可能是集显
                    elif len(gpu_list) == 1 and "rx" not in gpu_name_lower and "rtx" not in gpu_name_lowere_lower:
                        return "AMD 集成显卡"
            
            return ""
        except:
            # 如果WMI检测失败，尝试其他方法
            try:
                # 使用dxdiag信息检测
                result = subprocess.run(['dxdiag', '/t', 'dxdiag_output.txt'], capture_output=True, text=True)
                if result.returncode == 0:
                    # 读取dxdiag输出文件并分析
                    with open('dxdiag_output.txt', 'r', encoding='utf-8') as f:
                        dxdiag_content = f.read()
                    
                    # 检测Intel集成显卡
                    if 'Intel' in dxdiag_content and ('Graphics' in dxdiag_content or 'HD Graphics' in dxdiag_content):
                        return "Intel 集成显卡"
                    
                    # 检测AMD集成显卡
                    if 'AMD' in dxdiag_content and ('Radeon' in dxdiag_content or 'Vega' in dxdiag_content):
                        return "AMD 集成显卡"
                    
                    # 清理临时文件
                    os.remove('dxdiag_output.txt')
            except:
                pass
            
            return ""
    
    def _detect_integrated_gpu_linux(self) -> str:
        """Linux系统检测集成显卡"""
        try:
            # 尝试使用lspci命令检测Intel/AMD集成显卡
            result = subprocess.run(['lspci'], capture_output=True, text=True)
            if result.returncode == 0:
                lines = result.stdout.split('\n')
                for line in lines:
                    line_lower = line.lower()
                    # 检测Intel集成显卡
                    if 'intel' in line_lower and ('graphics' in line_lower or 'hd graphics' in line_lower):
                        return "Intel 集成显卡"
                    # 检测AMD集成显卡
                    elif 'amd' in line_lower and ('radeon' in line_lower or 'vega' in line_lower):
                        return "AMD 集成显卡"
            return ""
        except:
            return ""
    
    def _get_integrated_gpu_name(self, manufacturer: str) -> str:
        """获取集成显卡名称（备用方法）"""
        if manufacturer == "Intel":
            return "Intel 集成显卡"
        elif manufacturer == "AMD":
            return "AMD 集成显卡"
        else:
            return "集成显卡"
    
    def _detect_dedicated_gpu(self) -> str:
        """检测独立显卡"""
        try:
            if platform.system() == "Windows":
                return self._detect_dedicated_gpu_windows()
            else:
                return self._detect_dedicated_gpu_linux()
        except:
            return ""
    
    def _detect_dedicated_gpu_windows(self) -> str:
        """Windows系统检测独立显卡"""
        try:
            import wmi
            c = wmi.WMI()
            
            # 虚拟显示适配器关键词列表
            virtual_adapters = [
                "todesk", "virtual", "display adapter", "remote", "microsoft", 
                "basic display", "software device", "vmware", "virtualbox",
                "parallels", "hyper-v", "qxl", "cirrus", "vbox", "vmware svga"
            ]
            
            # 真实显卡关键词列表
            real_gpu_keywords = [
                "nvidia", "geforce", "rtx", "gtx", "quadro", "tesla",
                "amd", "radeon", "rx", "vega", "firepro", "radeon pro",
                "intel arc", "intel iris", "intel hd graphics"
            ]
            
            for gpu in c.Win32_VideoController():
                gpu_name = gpu.Name
                if not gpu_name:
                    continue
                    
                gpu_name_lower = gpu_name.lower()
                
                # 排除虚拟显示适配器
                is_virtual = any(keyword in gpu_name_lower for keyword in virtual_adapters)
                if is_virtual:
                    continue
                
                # 排除集成显卡
                is_integrated = ("intel" in gpu_name_lower and "graphics" in gpu_name_lower) or \
                               ("amd" in gpu_name_lower and ("radeon graphics" in gpu_name_lower or "vega" in gpu_name_lower))
                if is_integrated:
                    continue
                
                # 检查是否为真实显卡
                is_real_gpu = any(keyword in gpu_name_lower for keyword in real_gpu_keywords)
                if is_real_gpu:
                    return gpu_name
            
            # 如果没有检测到真实显卡，返回空字符串
            return ""
        except:
            return ""
    
    def _detect_dedicated_gpu_linux(self) -> str:
        """Linux系统检测独立显卡"""
        try:
            # 尝试使用lspci命令检测NVIDIA/AMD显卡
            result = subprocess.run(['lspci'], capture_output=True, text=True)
            if result.returncode == 0:
                lines = result.stdout.split('\n')
                for line in lines:
                    if 'nvidia' in line.lower() or 'amd' in line.lower() or 'radeon' in line.lower():
                        # 排除集成显卡
                        if 'intel' not in line.lower():
                            if 'nvidia' in line.lower():
                                return "NVIDIA 独立显卡"
                            elif 'amd' in line.lower() or 'radeon' in line.lower():
                                return "AMD 独立显卡"
            return ""
        except:
            return ""
    
    def _get_gpu_vendor(self, gpu_name: str) -> str:
        """获取GPU厂商"""
        gpu_name_lower = gpu_name.lower()
        
        if "nvidia" in gpu_name_lower or "geforce" in gpu_name_lower:
            return "NVIDIA"
        elif "amd" in gpu_name_lower or "radeon" in gpu_name_lower:
            return "AMD"
        elif "intel" in gpu_name_lower:
            return "Intel"
        else:
            return "未知"
    
    def has_cpu(self) -> bool:
        """是否有CPU"""
        return bool(self.cpu_info)
    
    def has_integrated_gpu(self) -> bool:
        """是否有集成显卡"""
        return len(self.gpu_info["integrated_gpus"]) > 0
    
    def has_dedicated_gpu(self) -> bool:
        """是否有独立显卡"""
        return len(self.gpu_info["dedicated_gpus"]) > 0
    
    def get_cpu_info(self) -> Dict:
        """获取CPU信息"""
        return self.cpu_info
    
    def get_integrated_gpu_info(self) -> List[Dict]:
        """获取集成显卡信息"""
        return self.gpu_info["integrated_gpus"]
    
    def get_dedicated_gpu_info(self) -> List[Dict]:
        """获取独立显卡信息"""
        return self.gpu_info["dedicated_gpus"]
    
    def get_hardware_summary(self) -> str:
        """获取硬件摘要信息"""
        summary = []
        
        # CPU信息
        if self.cpu_info:
            summary.append(f"CPU: {self.cpu_info['name']} ({self.cpu_info['cores']}核{self.cpu_info['threads']}线程)")
        
        # 集成显卡信息
        if self.has_integrated_gpu():
            igpu = self.gpu_info["integrated_gpus"][0]
            summary.append(f"集显: {igpu['name']}")
        
        # 独立显卡信息
        if self.has_dedicated_gpu():
            dgpu = self.gpu_info["dedicated_gpus"][0]
            summary.append(f"独显: {dgpu['name']}")
        
        return " | ".join(summary)


# 全局硬件检测器实例
hardware_detector = HardwareDetector()


if __name__ == "__main__":
    # 测试硬件检测
    detector = HardwareDetector()
    
    print("=== 硬件检测结果 ===")
    print(f"系统平台: {detector.system_info['platform']}")
    print(f"CPU信息: {detector.cpu_info}")
    print(f"是否有集显: {detector.has_integrated_gpu()}")
    print(f"是否有独显: {detector.has_dedicated_gpu()}")
    print(f"集显信息: {detector.get_integrated_gpu_info()}")
    print(f"独显信息: {detector.get_dedicated_gpu_info()}")
    print(f"硬件摘要: {detector.get_hardware_summary()}")